package com.wondertek.service.quartz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.wondertek.service.entity.sys.SysJobLogPo;
import com.wondertek.service.entity.sys.SysJobPo;
import com.wondertek.service.service.sys.ISysJobLogService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

/**
 * 抽象quartz调用
 */
@Slf4j
public abstract class AbstractQuartzJob implements Job {

    /**
     * 线程本地变量
     */
    private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.info("-------->>> 系统定时任务开始执行 <<<----------");
        Object obj = context.getMergedJobDataMap().get(JobInvokeUtil.TASK_PROPERTIES);
        SysJobPo sysJobPo = new SysJobPo();
        //修改通过拷贝类实现
        BeanUtil.copyProperties(context.getMergedJobDataMap().get(JobInvokeUtil.TASK_PROPERTIES), sysJobPo);
        try {
            before(context, sysJobPo);
            if (ObjectUtil.isNotEmpty(sysJobPo)) {
                doExecute(context, sysJobPo);
            }
            after(context, sysJobPo, null);
        } catch (Exception e) {
            after(context, sysJobPo, e);
        }
        log.info("-------->>> 系统定时任务执行结束 <<<----------");
    }

    /**
     * 执行前
     *
     * @param context  工作执行上下文对象
     * @param sysJobPo 系统计划任务
     */
    protected void before(JobExecutionContext context, SysJobPo sysJobPo) {
        threadLocal.set(new Date());
    }

    /**
     * 执行后
     *
     * @param context 工作执行上下文对象
     * @param sysJob  系统计划任务
     */
    protected void after(JobExecutionContext context, SysJobPo sysJob, Exception e) {
        Date startTime = threadLocal.get();
        threadLocal.remove();
        final SysJobLogPo sysJobLog = new SysJobLogPo();
        sysJobLog.setJobName(sysJob.getJobName());
        sysJobLog.setJobId(sysJob.getId());
        sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
        sysJobLog.setCreateTime(new Date());
        long runMs = System.currentTimeMillis() - startTime.getTime();
        sysJobLog.setTimes((int) runMs);
        if (e != null) {
            log.error("任务执行失败，任务ID：" + sysJobLog.getJobId(), e);
            sysJobLog.setStatus(1);
            String errorMsg = ExceptionUtil.stacktraceToOneLineString(e, 2000);
            sysJobLog.setError(errorMsg);
        } else {
            // 任务状态 0：成功 1：失败
            sysJobLog.setStatus(0);
            sysJobLog.setError("执行成功!");
        }
        // 写入数据库当中
        SpringUtil.getBean(ISysJobLogService.class).save(sysJobLog);
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context  工作执行上下文对象
     * @param sysJobPo 系统计划任务
     * @throws Exception 执行过程中的异常
     */
    protected abstract void doExecute(JobExecutionContext context, SysJobPo sysJobPo) throws Exception;
}
